#include "scene.h"


Scene::Scene(QString name, Camera* camera, QObject *parent):
    _shapes(),
    _name(name),
    QObject(parent)
{
    _camera = camera;
    _csg = new CSG(nullptr);
}

Scene::~Scene()
{
    delete _csg;
}

const QVector<Shape *> &Scene::shapes() const
{
    return _shapes;
}

const QVector<Shape*> Scene::emitters() const
{
    QVector<Shape*> emmitters;
    foreach (Shape* shape, _shapes) {
        if(shape->isEmiter())
            emmitters.append(shape);
    }
    return emmitters;
}

const Shape *Scene::shape(const QString name) const
{
    foreach (Shape* shape, _shapes) {
        if(shape->_name == name)
            return shape;
    }
    return (Shape*)0;
}

bool Scene::removeShape(const QString name)
{
    //    foreach (Shape* shape, _shapes) {
    //        _shapes.removeAll(shape);
    //        return true;
    //    }
    return false;
}

void Scene::addShape(Shape *shape)
{
    if(_csg->root() == nullptr)
        _csg->setRoot(new Node(shape));
    else
        _csg->setRoot( new Node(Node::Union_NodeType,
                                _csg->root(),
                                new Node(shape)));
}

void Scene::addShape(CSG *shape)
{
    if(_csg->root() == nullptr)
        _csg->setRoot(shape->root());
    else
        _csg->setRoot( new Node(Node::Union_NodeType,
                                _csg->root(),
                                shape->root()));
}

QString Scene::name() const
{
    return _name;
}

void Scene::setName(QString value)
{
    _name = value;
}

const Shape* Scene::intersect(const Ray &ray, double &distance, Vector &normal) const
{
    const Shape* value = nullptr;
    Vector _normal[2];
    double d[2];
    _csg->root()->intersect(&value,ray,d,_normal);
    distance=d[_IN];
    normal=_normal[_IN];
    return value;
}

Camera *Scene::camera() const
{
    return _camera;
}

void Scene::setCamera(Camera *value)
{
    _camera = value;
}

QDataStream &operator <<(QDataStream & s, const Scene & scene)
{
    s << scene.name();
    s << *scene.camera();
    s << scene.shapes().size();
    foreach (Shape* shape, scene.shapes()) {
        s << typeid(shape).hash_code();
        s << *shape;
    }
    return s;
}


QDataStream &operator >>(QDataStream & s, Scene & scene)
{
    Shape* shape;
    qint32 size;
    s >> scene._name;
    s >> *scene._camera;
    s >> size;
    scene._shapes.clear();
    for(int i=0; i < size; i++) {
        s >> *shape;
        scene._shapes.append(shape);
    }
    return s;
}

//    for (QVector<Shape*>::const_iterator i = _shapes.begin(); i != _shapes.end(); i++) {
//        Shape* shape = (Shape*)(*i);
////        if(shape->getBoundingBox().intersect(ray)) {
//            if(shape->intersect(ray,d,_normal)) {
//                if (value==0) {
//                    distance=d[_IN];
//                    value=shape;
//                    normal = _normal[_IN];
//                }
//                else {
//                    if (d[_IN]<distance){
//                        distance=d[_IN];
//                        value=shape;
//                        normal = _normal[_IN];
//                    }
//                }
//            }
////        }
//    }
